package com.js.service.bot.response;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.js.common.annotation.ResponseClass;
import com.js.common.annotation.ResponseCommand;
import com.js.common.core.BotHandler;
import com.js.service.bot.core.StorageService;
import net.mamoe.mirai.message.data.MessageChain;
import net.mamoe.mirai.message.data.MessageChainBuilder;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.HttpCookie;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.FutureTask;

@Service
@EnableScheduling
@Scope("prototype")
@ResponseClass("今日简报")
public class ToDayService extends BotHandler {

    @Resource
    private StorageService storageService;
    @Resource
    private ThreadPoolTaskExecutor wsExecutor;

    //接口地址
    private final Map<String, String> URL_MAP = new HashMap<>();
    //请求头
    private final Map<String, String> headers = new HashMap<>();

    @ResponseCommand(
            value = "今日简报",
            name = "今日简报"
    )
    public MessageChain today(Long userId, Long targetId, String command, MessageChain messageChain) throws IOException {
        String wxToken = storageService.getStorageValue(getMaster(), "WeChatToken");
        String cookie = storageService.getStorageValue(getMaster(), "WeChatCookies");
        if(StrUtil.isEmpty(wxToken) || StrUtil.isEmpty(cookie)){
            return startLogin(userId, targetId);
        }

        Map<String, Object> params = new HashMap<>(10);
        params.put("action", "list_ex");
        params.put("begin", "0");
        params.put("count", "5");
        params.put("fakeid", "MjM5MTA3NTQwNQ==");
        params.put("token", wxToken);
        params.put("type", "9");
        params.put("query", "");
        params.put("lang", "zh_CN");
        params.put("f", "json");
        params.put("ajax", "1");

        String res = HttpRequest.get("https://mp.weixin.qq.com/cgi-bin/appmsg")
                .header("cookie", cookie)
                .form(params)
                .execute().body();
        JSONObject findExList = JSONUtil.parseObj(res);
        if(findExList.containsKey("base_resp") && findExList.getJSONObject("base_resp").getStr("err_msg").equals("invalid session")){
            return startLogin(userId, targetId);
        }
        String link = null;
        JSONArray appMsgList = findExList.getJSONArray("app_msg_list");
        for (int i = 0; i < appMsgList.size(); i++) {
            JSONObject article = appMsgList.getJSONObject(i);
            if(article.getStr("title").startsWith("今日简报")){
                link = article.getStr("link");
                break;
            }
        }
        if(link != null) {
            link = link.replaceAll("http", "https");
            String html = HttpUtil.get(link);
            List<String> srcs = ReUtil.findAll("cdn_url: '(.*?)',", html, 1);
            String src = srcs.get(0);

            BufferedImage bufferedImage = ImageIO.read(IoUtil.toStream(HttpUtil.downloadBytes(src)));
            int srcWidth = bufferedImage.getWidth();
            int srcHeight = bufferedImage.getHeight();
            Image image = bufferedImage.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT);
            ImageFilter cropFilter = new CropImageFilter(0, 500, srcWidth, srcHeight - 900);
            Image img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter));
            BufferedImage tag = new BufferedImage(srcWidth, srcHeight - 500, BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(img, 0, 0, srcWidth, srcHeight - 500, null); // 绘制切割后的图
            g.dispose();

            // 添加白底水印盖掉二维码
            Graphics2D g2 = tag.createGraphics();
            Image pressImg = ImageIO.read(this.getClass().getResourceAsStream("/images/pressImg.png"));
            int wideth_biao = pressImg.getWidth(null);
            int height_biao = pressImg.getHeight(null);
            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
            g2.drawImage(pressImg, 340, tag.getHeight() - 110, wideth_biao, height_biao, null);
            g2.dispose();
            // 添加水印结束

            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            ImageIO.write(tag, "png", stream);
            String base64 = Base64.encode(stream.toByteArray());
            stream.flush();
            stream.close();

            MessageChainBuilder result = new MessageChainBuilder();
            result.append("base64://"+base64);
            return result.build();
        }
        return null;
    }

    public ToDayService() {
        //初始化登录cookie
        URL_MAP.put("startLogin", "https://mp.weixin.qq.com/cgi-bin/bizlogin?action=startlogin");

        //二维码图片接口
        URL_MAP.put("getqrcode", "https://mp.weixin.qq.com/cgi-bin/scanloginqrcode");

        //二维码扫描状态接口
        URL_MAP.put("qrcodeAsk", "https://mp.weixin.qq.com/cgi-bin/scanloginqrcode");

        //扫码确认后，登录接口
        URL_MAP.put("bizlogin", "https://mp.weixin.qq.com/cgi-bin/bizlogin?action=login");

        //扫码确认后，登录接口
        URL_MAP.put("searchbiz", "https://mp.weixin.qq.com/cgi-bin/searchbiz");

        //扫码确认后，登录接口
        URL_MAP.put("findListEx", "https://mp.weixin.qq.com/cgi-bin/appmsg");

        headers.put("referer", "https://mp.weixin.qq.com/");
        headers.put("userAgent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36");
        headers.put("xRequestedWith", "XMLHttpRequest");
    }

    public MessageChain startLogin(Long userId, Long targetId){
        String sessionid = "" + System.currentTimeMillis() + (int)(Math.random()*100);

        Map<String, String> params = new HashMap<>();
        params.put("sessionid", sessionid);
        params.put("userlang", "zh_CN");
        params.put("redirect_url", "");
        params.put("login_type", "3");
        params.put("token", "");
        params.put("lang", "zh_CN");
        params.put("f", "json");
        params.put("ajax", "1");

        String res = HttpRequest.post(URL_MAP.get("startLogin"))
                .addHeaders(headers)
                .formStr(params)
                .execute().body();
        System.out.println(res);
        String qrCode = getQRCode();

        MessageChainBuilder result = new MessageChainBuilder();
        result.append("请先登陆");
        result.append(newline());
        result.append("base64://"+qrCode);
        wsExecutor.execute(() -> {
            future(userId, targetId);
        });
        return result.build();
    }

    public String getQRCode() {
        Map<String, String> params = new HashMap<>();
        params.put("action", "getqrcode");
        params.put("random", System.currentTimeMillis() + "");
        HttpRequest request = HttpRequest.get(URL_MAP.get("getqrcode"));
        byte[] bytes = request.addHeaders(headers)
                .formStr(params)
                .execute().bodyBytes();

        cookiesStorage(request);

        return Base64.encode(bytes);
    }

    public void cookiesStorage(HttpRequest request){
        List<HttpCookie> cookies = request.getCookieManager().getCookieStore().getCookies();
        String[] s = new String[cookies.size()];
        for (int i = 0; i < cookies.size(); i++) {
            HttpCookie cookie = cookies.get(i);
            s[i] = cookie.getName() + "=" + StrUtil.nullToDefault(cookie.getValue(), "");
        }
        storageService.addStorage(getMaster(), "WeChatCookies", ArrayUtil.join(s, "; "));
    }

    public void future(Long userId, Long targetId){
        // 3.轮询二维码状态接口
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            while (true) {
                Integer status = askQRCode();
                if (status == 3) {
                    System.out.println("二维码已过期");
                    return 3;
                } else if (status == 4) {
                    System.out.println("已扫码，等待确认");
                } else if (status == 1) {
                    System.out.println("已确认登录，请稍后...");
                    return 1;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        while (true) {
            Thread queryThread = new Thread(futureTask);
            queryThread.start();
            if (!futureTask.isDone()) {
                System.out.println("--正在查询扫码状态，请尽快扫码！");
            }

            try {
                Integer integer = futureTask.get();
                if (integer == 1) {
                    System.out.println("扫码成功");
                    bizlogin();
                    MessageChainBuilder result = new MessageChainBuilder();
                    result.append("登陆成功");
                    send(userId, targetId, result.build());
                    break;
                }else if(integer == 3){
                    System.out.println("二维码过期，结束此次登陆");
                    break;
                }
            } catch (Exception e) {
                System.out.println("查询接口出错了");
                break;
            }
        }
    }

    public Integer askQRCode() {
        Map<String, String> params = new HashMap<>(5);
        params.put("action", "ask");
        params.put("token", "");
        params.put("lang", "zh_CN");
        params.put("f", "json");
        params.put("ajax", "1");

        headers.put("cookie", storageService.getStorageValue(getMaster(), "WeChatCookies"));

        String result = HttpRequest.get(URL_MAP.get("qrcodeAsk"))
                .addHeaders(headers)
                .formStr(params)
                .execute().body();
        return JSONUtil.parseObj(result).getInt("status");
    }

    @Scheduled(cron = "0 0 7,15,22 * * ?")
    public void bizlogin() {
        Map<String, String> params = new HashMap<>(10);
        params.put("userlang", "zh_CN");
        params.put("redirect_url", "");
        params.put("cookie_forbidden", "0");
        params.put("cookie_cleaned", "0");
        params.put("plugin_used", "0");
        params.put("login_type", "3");
        params.put("token", "");
        params.put("lang", "zh_CN");
        params.put("f", "json");
        params.put("ajax", "1");

        headers.put("cookie", storageService.getStorageValue(getMaster(), "WeChatCookies"));

        HttpRequest httpRequest = HttpRequest.post(URL_MAP.get("bizlogin"));
        String res = httpRequest.addHeaders(headers)
                .formStr(params)
                .execute().body();
        String url = JSONUtil.parseObj(res).getStr("redirect_url");
        String token = HttpUtil.decodeParams(url, "utf-8").get("token").get(0);
        cookiesStorage(httpRequest);
        storageService.addStorage(getMaster(), "WeChatToken", token);
    }
}
